#ifndef TNGRAPH_H
#define TNGRAPH_H

//#define MARK_VISITED 0
//#define MARK_SUBTREE 1
//#define MARK_BASE (1<<30)

//#define MASK_VISITED (MARK_BASE << MARK_VISITED)
//#define MASK_SUBTREE (MARK_BASE << MARK_SUBTREE)

//#define THE_MASK 0x3FFFFFFF
//#define MASK(x) ((x) & THE_MASK)

#define GRAPH_MODE_TEXT 0
#define GRAPH_MODE_BINARY 1
#define GRAPH_MODE_MMAP 2

#ifndef ERR
#define ERR stderr
#endif

typedef unsigned int uint;
typedef unsigned char uchar;
typedef signed char sch;

struct tnnode{
 uint size;
 uint * neighbours;
} __attribute__((__packed__));

struct tngraph{
 unsigned char graphtype;
 uint size;
 struct tnnode*nodes;
};


#define MARKNODE(nn,bits) {unsigned long n=(nn);bits[n/8]|=(1<<(n%8));}
#define UNMARKNODE(nn,bits) {unsigned long n=(nn);bits[n/8]&=~(1<<(n%8));}
#define ISMARKED(n,bits) ((bits[(n)/8]&(1<<((n)%8)))!=0)

#define MALLOCMARKS(s) (calloc(1,1+(s)/8))
#define GETNEIGHBOURS(g,n,res,sz) {(res)=(g)->nodes[(n)].neighbours;if((res)==NULL){fprintf(ERR,"cannot get neighbours for node %u!\n",(n));abort();};(sz)=(g)->nodes[(n)].size;}


#define GETNODE(g,n) (((g)->nodes[(n)].neighbours==NULL)?NULL:((g)->nodes+(n)) )


extern struct tngraph* mkgraph(uint size);
extern void initnode(struct tngraph*this, uint node, uint nneigh);
extern void freenode(struct tngraph*this, uint node);
extern void freegraph(struct tngraph*this);
extern int existsedge(struct tngraph*this, uint node1, uint node2);
extern int nodecount(struct tngraph*this);
extern long long edgecount(struct tngraph*this);
extern struct tngraph* loadgraph(const char * file, uint mode);
extern uint getrandomnode(struct tngraph*g);
extern uint getrandomunmarkednode(struct tngraph*g,unsigned char*marks);

#endif
